package com.chushouya.common.applet;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.chushouya.common.enums.RedisKeys;
import com.chushouya.common.util.AesUtil;
import com.general.framework.core.exception.Ex;
import com.general.framework.core.lang.Jsons;
import com.general.framework.core.lang.Strings;
import com.general.framework.core.lang.Validate;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 字节跳动小程序
 */
public class ByteDanceClient {

    private final Logger log = LoggerFactory.getLogger(ByteDanceClient.class);
    private static final int SUCCESS = 0;
    private final String appid;
    private final String secret;

    public ByteDanceClient(String appid, String secret) {
        this.appid = appid;
        this.secret = secret;
    }

    /**
     * 字节小程序授权登录
     * <a href="https://microapp.bytedance.com/docs/zh-CN/mini-app/develop/server/log-in/code-2-session">文档</a>
     */
    public String jscode2session(String code) {

        Map<String, Object> map = new HashMap<>();
        map.put("appid", appid);
        map.put("secret", secret);
        map.put("code", code);

        String url = "https://developer.toutiao.com/api/apps/v2/jscode2session";
        String resp = HttpUtil.post(url, Jsons.toJsonString(map));

        JSONObject json = JSON.parseObject(resp);
        if (json.getIntValue("err_no") != SUCCESS) {
            log.error("字节小程序授权登录异常: {}", resp);
            throw Ex.business(json.getString("err_tips"));
        }

        JSONObject data = json.getJSONObject("data");

        //获取手机号码解密需要用到sessionKey
        String sessionKey = data.getString("session_key");
        String openid = data.getString("openid");
        RedisHolder.REDIS_CACHE.setCacheObject(Strings.format(RedisKeys.SESSION_KEY, appid, openid), sessionKey,1L, TimeUnit.DAYS);

        return openid;
    }


    /**
     * 字节小程序获取用户手机号码
     * <a href="https://microapp.bytedance.com/docs/zh-CN/mini-app/develop/component/acquire-phone-number-acquire/">文档</a>
     * 解密之后的数据如下
     * {
     * "phoneNumber": "138xxxxxxxx", // 用户绑定的手机号（国外手机号会有区号）
     * "purePhoneNumber": "138xxxxxxxx", // 没有区号的手机号
     * "countryCode": "86", // 区号
     * "watermark": {
     * "appid": "ttxxxxxxxxxxxxxxxx",
     * "timestamp": 15000000000000000
     * }
     * }
     *
     * @param openid        用户id
     * @param iv            小程序返回的iv
     * @param encryptedData 小程序返回的加密数据
     * @return 手机号码
     */
    public String getPhoneNumber(String openid, String iv, String encryptedData) {

        Validate.isBlank(openid, "用户openid不能为空");
        Validate.isBlank(iv, "iv不能为空");
        Validate.isBlank(encryptedData, "加密数据不能为空");

        String sessionKey = RedisHolder.REDIS_CACHE.getCacheObject(Strings.format(RedisKeys.SESSION_KEY, appid, openid));
        if (Strings.isBlank(sessionKey)) {
            throw Ex.business("小程序登录状态过期, 请重新登录");
        }

        //解密数据
        try {
            String raw = AesUtil.decode("AES/CBC/PKCS7Padding", Base64.decodeBase64(iv), Base64.decodeBase64(sessionKey), Base64.decodeBase64(encryptedData));
            return JSON.parseObject(raw).getString("purePhoneNumber");
        } catch (Exception e) {
            log.error("aes解密异常", e);
            throw Ex.business("数据解密异常");
        }
    }

}
